package cn.jilian.sys.service.support.loaders;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.transaction.Transactional;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import cn.jilian.dao.MenuDAO;
import cn.jilian.entity.Menu;
import cn.jilian.entity.MenuGroup;
import cn.jilian.entity.MenuPage;
import cn.jilian.sys.service.support.MenuLoader;
import cn.jilian.sys.service.support.MenuSortable;


public class SysMenuLoader implements MenuLoader {

	
	private MenuDAO menuDAO;
	
	
	private Map<Long,Menu> allMenu;
	
	private Map<Long,List<Menu>> cacheMenuData;
	
	private Integer rankId;
	
	
	 
	
	public SysMenuLoader(MenuDAO menuDAO,Integer rankId) {
		this.menuDAO=menuDAO;
		this.rankId=rankId;
		refresh();
	}

	@Override
	public Menu getMenu(long id) {
		return allMenu.get(id);
	}

	@Override
	public List<Menu> getChildren(long id) {
		return cacheMenuData.get(id);
	}

	@Override
	public List<Menu> getAllTree() {
		return cacheMenuData.get(this.rankId.longValue());
	}

	@Override
	public Menu addMenu(Menu menu) {
		 menu= menuDAO.save(menu);
		 refresh();
		return menu;
	}

	@Override
	public Menu updateMenu(Menu menu) {
		Menu m=allMenu.get(menu.getId());
		if(m==null)
		return null;
		try {
		BeanUtils.copyProperties(m, menu);
		m=menuDAO.save(m);
		refresh();
		}catch(Exception e) {
			e.printStackTrace();
		}
		
		return m;
	}

	@Override
	@Transactional
	public int delete(long id) {
		Menu menu=allMenu.get(id);
		if(menu!=null) {
			menuDAO.delete(menu);
		}
		refresh();
		return 0;
	}

	@Override
	public void refresh() {
		allMenu=new ConcurrentHashMap<>();
		cacheMenuData=new ConcurrentHashMap<>();
		List<Menu> list=menuDAO.findByRank(rankId);
		for(Menu menu:list) {
			allMenu.put(menu.getId(), menu);
			Long fid=menu.getFid();
			List<Menu> children=cacheMenuData.get(fid);
			if(children==null) {
				children=new ArrayList<>();
				cacheMenuData.put(fid, children);
			}
			children.add(menu);
		}
		MenuSortable c=new MenuSortable();
		for(Map.Entry<Long, List<Menu>> e:cacheMenuData.entrySet()) {
			
			Collections.sort(e.getValue(), c);
		}
		
		for(Long id:cacheMenuData.keySet()){
			Menu menu=allMenu.get(id);
			if(menu instanceof MenuGroup) {
				MenuGroup group=(MenuGroup)menu;
				if(menu!=null) {
					List<Menu> menus=cacheMenuData.get(id);
					if(CollectionUtils.isNotEmpty(menus)) {
						group.setChildren(menus);
					}
				}
			}else if(menu instanceof MenuPage) {
				MenuPage page=(MenuPage)menu;
				if(menu!=null) {
					List<Menu> menus=cacheMenuData.get(id);
					if(CollectionUtils.isNotEmpty(menus)) {
						page.setChildren(menus);
						page.setLeaf(Boolean.FALSE);
					}
				}
			}
			
		}
	}

	@Override
	public void refresh(long id) {
		List<Menu> list=menuDAO.findByFidOrderBySeq(id);
		if(CollectionUtils.isNotEmpty(list)) {
			for(Menu n:list) {
				Menu old=allMenu.get(n.getId());
				if(old!=null) {
					if(n instanceof MenuPage) {
						MenuPage page=(MenuPage)n;
						page.setChildren(((MenuPage)old).getChildren());
					}else if(n instanceof MenuGroup) {
						MenuGroup page=(MenuGroup)n;
						page.setChildren(((MenuGroup)old).getChildren());
					}
					allMenu.put(n.getId(), n);
				}
			}
		}
		
		cacheMenuData.put(id, list);
		
		
	}
	
	

}
